package com.newhis.config;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.newhis.utils.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.PropertyPlaceholderHelper;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Configuration
public class NacosConfig {
    private static final Logger log = LoggerFactory.getLogger(NacosConfig.class);
    @Value(value = "${nacos.config.server-addr}")
    private String serverAddr;
    @Value(value = "${nacos.config.username}")
    private String username;
    @Value(value = "${nacos.config.password}")
    private String password;
    @Value(value = "${nacos.config.group}")
    private String group;
    @Value(value = "${nacos.config.init.namesapces}")
    private List<String> namespaces = new ArrayList<>();
    @Value(value = "${nacos.config.init.dataIds}")
    private List<String> dataIds = new ArrayList<>();
    private static final PropertyPlaceholderHelper placeholderHelper = new PropertyPlaceholderHelper("${", "}");
    private static ReadWriteLock cacheLock = new ReentrantReadWriteLock();
    private static ReentrantReadWriteLock.WriteLock writeLock = (ReentrantReadWriteLock.WriteLock)cacheLock.writeLock();

    @Bean
    public void initConfig() throws NacosException, IOException {
        log.info("初始化配置开始");
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, this.serverAddr);
        properties.put(PropertyKeyConst.USERNAME, this.username);
        properties.put(PropertyKeyConst.PASSWORD, this.password);
        if (namespaces == null || namespaces.isEmpty()){
            log.warn("-------------------初始化配置项失败，未配置namespaces");
            return;
        }
        if (dataIds == null || dataIds.isEmpty()){
            log.warn("-------------------初始化配置项失败，未配置dataIds");
            return;
        }
        for (String namespace : namespaces){
            properties.put(PropertyKeyConst.NAMESPACE, namespace);
            ConfigService configService = NacosFactory.createConfigService(properties);
            for(String dataId : dataIds){
                String content = configService.getConfigAndSignListener(dataId, this.group, 3000L, new Listener() {
                    @Override
                    public Executor getExecutor() {
                        return null;
                    }

                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        try {
                            writeLock.lock();
                            strToMap(configInfo);
                            configInfo = placeholderHelper.replacePlaceholders(configInfo, new NacosPlaceholderResolver());
                            strToMap(configInfo);
                        } catch (Exception e) {
                            log.error("--------------修改配置解析失败：", e);
                        }finally {
                            writeLock.unlock();
                        }
                    }
                });

                try {
                    writeLock.lock();
                    strToMap(content);
                    content = placeholderHelper.replacePlaceholders(content, new NacosPlaceholderResolver());
                    strToMap(content);
                } finally {
                    writeLock.unlock();
                }
            }
        }
        log.info("初始化配置结束，总配置项：{}", ConfigUtils.size());
    }

    private static final class NacosPlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver{

        @Override
        public String resolvePlaceholder(String placeholderName) {
            return ConfigUtils.get(placeholderName);
        }
    }
    private void strToMap(String content) throws IOException {
        Properties properties = new Properties();
        properties.load(new StringReader(content));
        Enumeration<?> enumeration = properties.propertyNames();
        while(enumeration.hasMoreElements()) {
            String strKey = (String)enumeration.nextElement();
            String strValue = properties.getProperty(strKey);
            ConfigUtils.put(strKey, strValue);
        }
    }
}
